/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-07-20 08:14:03
 * @LastEditTime: 2021-07-23 16:42:18
 * @Description:  This files is for 
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */
#include <string.h>
#include "ft_assert.h"
#include "parameters.h"
#include "generic_timer.h"
#include "qspi_hw.h"
#include "qspi.h"

void QSpiReset(QSpiCtrl *pCtrl)
{
    FT_ASSERTVOID(pCtrl);
    u32 regVal = 0;
    QSpiConfig *pConfig = &pCtrl->config;

    regVal = QSPI_CAP_FLASH_NUM(pConfig->devNum) | 
             (QSPI_CAP_FLASH_CAP_MASK && QSPI_CAP_FLASH_CAP(pConfig->capacity));
    QSPI_CAP_WRITE(pCtrl, regVal);
}

u32 QSpiGetLdPortData(QSpiCtrl *pCtrl, u8 *pBuf, size_t len)
{
    FT_ASSERTZERONUM(pCtrl && pBuf);
    u32 loop;
    u32 regVal;

    for (loop = 0; loop < len; loop++)
    {
        /* read 4 bytes one time */
        if (0 == loop % 4)
        {
            regVal = QSPI_LD_READ(pCtrl);
        }

        /* assign buf byte by byte */
        pBuf[loop] = (u8)((regVal >> (loop % 4) * 8) & 0xFF);
    }

    return QSPI_SUCCESS;
}

u32 QSpiSetLdPortData(QSpiCtrl *pCtrl, const u8 *pBuf, size_t len)
{
    FT_ASSERTZERONUM(pCtrl && pBuf);
    u32 regVal;

	if (1 == len) 
    {
		regVal = pBuf[0];
	} 
    else if (2 == len) 
    {
		regVal = pBuf[1];
		regVal = (regVal << 8) + pBuf[0];
	} else if (3 == len) 
    {
		regVal = pBuf[2];
		regVal = (regVal << 8) + pBuf[1];
		regVal = (regVal << 8) + pBuf[0];
	} else if (4 == len) 
    {
		regVal = pBuf[3];
		regVal = (regVal << 8) + pBuf[2];
		regVal = (regVal << 8) + pBuf[1];
		regVal = (regVal << 8) + pBuf[0];
	}

    QSPI_LD_WRITE(pCtrl, regVal);
    return QSPI_SUCCESS;
}

u32 QSpiWaitForCmd(QSpiCtrl *pCtrl)
{
    FT_ASSERTZERONUM(pCtrl);
    u32 cmdReg = 0;
    u32 ldReg;
    u32 timeout = QSPI_BUSY_TIMEOUT_US / 10;
    u32 ret = QSPI_SUCCESS;

    cmdReg |= QSPI_CMD_PORT_CMD_MASK & 
              QSPI_CMD_PORT_CMD(QSPI_FLASH_CMD_RDSR1);
    cmdReg |= QSPI_CMD_PORT_DATA_TRANS(0x1);
    cmdReg |= QSPI_CMD_PORT_CS_MASK & 
              QSPI_CMD_PORT_CS(pCtrl->config.channel); 

    QSPI_CMD_WRITE(pCtrl, cmdReg);
    do
    {
        timeout--;
        ldReg = QSPI_LD_READ(pCtrl);
        if (!timeout)
        {
            QSPI_ERROR("wait cmd timeout !!!");
            ret = QSPI_TIMEOUT;
            break;
        }
    } while (ldReg & 0x01);

    return ret;
}

void QSpiEnableWrite(QSpiCtrl *pCtrl)
{
    FT_ASSERTVOID(pCtrl);
    u32 cmdReg = 0;

    cmdReg |= QSPI_CMD_PORT_CMD_MASK &
              QSPI_CMD_PORT_CMD(QSPI_FLASH_CMD_WREN);
    cmdReg |= QSPI_CMD_PORT_CLK_SEL_MASK &
              QSPI_CMD_PORT_CLK_SEL(pCtrl->config.clkDiv);  
    cmdReg |= QSPI_CMD_PORT_CS_MASK & 
              QSPI_CMD_PORT_CS(pCtrl->config.channel); 

    QSPI_CMD_WRITE(pCtrl, cmdReg);
    QSPI_LD_WRITE(pCtrl, 0x0);
    return;
}

void QSpiDisableWrite(QSpiCtrl *pCtrl)
{
    FT_ASSERTVOID(pCtrl);
    u32 cmdReg = 0;

    cmdReg |= QSPI_CMD_PORT_CMD_MASK &
              QSPI_CMD_PORT_CMD(QSPI_FLASH_CMD_WRDI); 
    cmdReg |= QSPI_CMD_PORT_CLK_SEL_MASK &
              QSPI_CMD_PORT_CLK_SEL(pCtrl->config.clkDiv);  
    cmdReg |= QSPI_CMD_PORT_CS_MASK & 
              QSPI_CMD_PORT_CS(pCtrl->config.channel); 

    QSPI_CMD_WRITE(pCtrl, cmdReg);
    QSPI_LD_WRITE(pCtrl, 0x0);
    return;                         
}